﻿using DotNetImage.Types;
using System;
using System.Windows;

namespace DotNetImage.Imaging.Filters
{
    public class Sphere : FilterBase
    {
        FloatPoint[,] floatingPoints = null;
        Point[,] points = null;
        Point mid = new Point();

        public bool Smoothing { get; set; }


        protected override void PrepareData(DotNetImage bmp)
        {
            bmp.CreatePixelCopy();
            points = new Point[nWidth, nHeight];
            floatingPoints = new FloatPoint[nWidth, nHeight];
            mid.X = nWidth / 2;
            mid.Y = nHeight / 2;
        }

        protected override void ProcessPixel(ref Pixel pix, uint x, uint y)
        {
            uint trueX = x - (uint)mid.X;
            uint trueY = y - (uint)mid.Y;
            double theta = Math.Atan2((trueY), (trueX));
            double radius = Math.Sqrt(trueX * trueX + trueY * trueY);

            double newRadius = radius * radius / (Math.Max(mid.X, mid.Y));

            double newX = mid.X + (newRadius * Math.Cos(theta));

            if (newX > 0 && newX < nWidth)
            {
                floatingPoints[x, y].X = newX;
                points[x, y].X = (int)newX;
            }
            else
            {
                floatingPoints[x, y].X = floatingPoints[x, y].Y = 0.0;
                points[x, y].X = points[x, y].Y = 0;
            }

            double newY = mid.Y + (newRadius * Math.Sin(theta));
            if (newY > 0 && newY < nHeight && newX > 0 && newX < nWidth)
            {
                floatingPoints[x, y].Y = newY;
                points[x, y].Y = (int)newY;
            }
            else
            {
                floatingPoints[x, y].X = floatingPoints[x, y].Y = 0.0;
                points[x, y].X = points[x, y].Y = 0;
            }
        }

        protected override void PostProcessing(DotNetImage bmp)
        {
            base.PostProcessing(bmp);
            if (Smoothing)
            {
                OffsetFilterAntiAlias filter = new OffsetFilterAntiAlias();
                filter.Offset = floatingPoints;
                filter.Apply(bmp);
            }
            else
            {
                OffsetFilterAbs filter = new OffsetFilterAbs();
                filter.Offset = points;
                filter.Apply(bmp);
            }            
        }
    }
}
